package com.topc.participant.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.topc.base.constant.RedisConstant;
import com.topc.base.exception.Asserts;
import com.topc.base.model.PageParams;
import com.topc.base.model.PageResult;
import com.topc.base.utils.PageUtils;
import com.topc.core.sevice.RedisService;
import com.topc.participant.model.dto.QueryUserDto;
import com.topc.participant.model.dto.SaveUserDto;
import com.topc.participant.model.po.UserInfo;
import com.topc.participant.mapper.UserInfoMapper;
import com.topc.participant.model.vo.UserShowVo;
import com.topc.participant.service.IEmailService;
import com.topc.participant.service.IUserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author Gogoing
 */
@Slf4j
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements IUserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private IEmailService emailService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void logout(String userNumber) {
        redisService.del(RedisConstant.USER_ONLINE_NUMBER+userNumber);
    }

    @Override
    public UserInfo getUserInfoByNumber(String number) {
        return this.getBaseMapper().getUserInfoByNumber(number).setPassword(null);
    }

    @Override
    public void switchUserRole(Long oldRoleId, Long newRoleId) {
        LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(UserInfo::getRoleId,newRoleId).eq(UserInfo::getRoleId,oldRoleId);
        this.update(updateWrapper);
    }

    @Override
    public Boolean isHasRoleInUser(Long roleId) {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getRoleId,roleId);
        int count = this.count(queryWrapper);
        return count>0;
    }

    @Override
    public PageResult<UserShowVo> searchInfoByPage(PageParams pageParams, QueryUserDto queryUserDto) {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(UserInfo::getId,UserInfo::getNumber,UserInfo::getName,UserInfo::getAvatarUrl,UserInfo::getUsername,UserInfo::getStudentClass,UserInfo::getCreateTime,UserInfo::getStatus)
                .like(ObjectUtil.isNotEmpty(queryUserDto.getName()),UserInfo::getName,queryUserDto.getName())
                .like(ObjectUtil.isNotEmpty(queryUserDto.getNumber()),UserInfo::getNumber,queryUserDto.getNumber())
                .eq(queryUserDto.getRoleId()!=-1,UserInfo::getRoleId,queryUserDto.getRoleId());
        Page page = this.page(pageParams.page(), queryWrapper);
        List<UserInfo> records = page.getRecords();
        List<UserShowVo> collect = records.stream().map(UserShowVo::new).collect(Collectors.toList());
        page.setRecords(collect);
        return PageUtils.pageToResult(page);
    }

    @Override
    public Long saveUserInfo(SaveUserDto saveUserDto) {
        boolean isNumber = NumberUtil.isNumber(saveUserDto.getNumber());
        if (!isNumber) Asserts.fail("账号格式错误");
        String password = RandomUtil.randomString(8);
        UserInfo userInfo = new UserInfo();
        BeanUtil.copyProperties(saveUserDto,userInfo);
        userInfo.setPassword(passwordEncoder.encode(password));
        Object emailLimit = redisService.get(RedisConstant.USER_LIMIT_EMAIL_TIME + saveUserDto.getNumber());
        if (ObjectUtil.isNotEmpty(emailLimit)) Asserts.fail("不能再同一分钟给同一个账号发邮件");
        boolean save = this.save(userInfo);
        if (!save) Asserts.fail("保存失败");
        redisService.set(RedisConstant.USER_LIMIT_EMAIL_TIME + saveUserDto.getNumber(), LocalDateTime.now(),6000);
        emailService.sendPassword("user",saveUserDto.getEmail(), password,saveUserDto.getName());
        return userInfo.getId();
    }

    @Override
    public void updateUserStatus(String number, int status) {
        LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(UserInfo::getStatus,status).eq(UserInfo::getNumber,number);
        boolean update = this.update(updateWrapper);
        if (!update) Asserts.fail("修改未成功或者未有此用户");
    }


    @Override
    public List<String> getNameListByNumber(List<String> userNumbers) {
        List<String> names=userInfoMapper.getNameListByNumber(userNumbers);
        System.out.println(names);
        return names;
    }

    @Override
    public void updateUserPwd(String number,String newPwd, String originPwd) {
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(UserInfo::getPassword)
                .eq(UserInfo::getNumber,number);
        String password = userInfoMapper.selectOne(queryWrapper).getPassword();
        System.out.println("encode==============================>"+password);
        System.out.println("origin================================>"+originPwd);
        boolean matches = passwordEncoder.matches(originPwd,password);
        System.out.println(matches);
        if (!matches){
            Asserts.fail("原密码错误");
        }
        LambdaUpdateWrapper<UserInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(UserInfo::getPassword,passwordEncoder.encode(newPwd))
                .eq(UserInfo::getNumber,number);
        boolean update = this.update(updateWrapper);
        if (!update){
            Asserts.fail("修改密码失败");
        }
    }

    @Override
    public void saveListByExcel(MultipartFile file) {
        List<SaveUserDto> saveUserDtos = new ArrayList<>();
        try (InputStream inputStream = file.getInputStream()) {
            Workbook workbook = new XSSFWorkbook(inputStream);
            Sheet sheet = workbook.getSheetAt(0);
            int maxRow = sheet.getLastRowNum();
            System.out.println("lastRowNum=======>"+maxRow);
            int row_num=0;
            for (Row row : sheet) {
                if (row_num>maxRow){
                    break;
                }
                if (row.getRowNum() == 0) continue; // 跳过标题行
                SaveUserDto saveUserDto = new SaveUserDto();
                //学号
                saveUserDto.setNumber(row.getCell(0).getStringCellValue());
                //姓名
                saveUserDto.setName(row.getCell(1).getStringCellValue());
                saveUserDto.setUsername(row.getCell(1).getStringCellValue());
                //班级
                saveUserDto.setStudentClass(row.getCell(2).getStringCellValue());
                //邮箱
                saveUserDto.setEmail(row.getCell(3).getStringCellValue());
                //身份(学生)
                saveUserDto.setRoleId(5);
                saveUserDtos.add(saveUserDto);
                row_num++;
            }
            System.out.println("==================>"+saveUserDtos);
            for (SaveUserDto saveUserDto:saveUserDtos){
                Long l = this.saveUserInfo(saveUserDto);
            }
        }catch (Exception e){
            Asserts.fail("用户导入失败"+e);
        }
    }


}
